#include <cstdio>
#include <cstdlib>
//#include <tchar.h>

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/video/video.hpp"
#include <opencv2/gpu/gpu.hpp>


#include "VideoRead.h"

#include "FeatureComputer.h"

#include "Classifier.h"

#include "Bagging.h"

#include "Interface.h"


int main(int argc, char * const argv[])
{
	LcInterface my_setting;

	int pick_num = 3;

	if(argc==1)
	{		
		//char *const setting_string[] ={ "","-a","-v","l","-t","P_02","-s", \
		//	"2000", "-e", "85000", "-r","1000","-p","P_02","-f","../../_FGS/","-y",".jpg"};

		char *const setting_string[] ={ "","-b","-v","l","-t","no1","-s", \
			"320", "-e", "9280", "-r","320","-p","no1","-f","../../_FGS/","-y",".jpg"};

		my_setting.input( 17 + 1 ,setting_string);
	}
	else my_setting.input( argc, argv);

	LcBagging bagging;

	if( my_setting.IF_TRAIN )
	{

		LcVideoRead * my_reader = my_setting.getTrainVideop();

		vector< float > avg_lbs; avg_lbs.clear();
		avg_lbs.reserve( my_reader->getN() + 10);

		vector< int > frm_id; frm_id.clear();
		frm_id.reserve( my_reader->getN() + 10);

		for(int i = 0; i < 10000; i++)
		{
			Mat frm;

			int statu = my_reader->readNext( frm );

			if(statu) break;

			Mat gt;

			my_reader->getLabel( gt );

			Mat gt_float;

			gt.convertTo( gt_float, 5);

			float _avg_lb = - lc::reduceMat( gt_float, CV_REDUCE_AVG);

			avg_lbs.push_back( _avg_lb );	
			frm_id.push_back( my_reader->getf());
		}

		vector< int > sort_id;		

		lc::argsort( avg_lbs, sort_id );

		vector< int > frm_pick_id; frm_pick_id.clear();

		cout << "pick frame id : " ;
		for(int i = 0 ;i < pick_num ; i++)
		{
			int id = sort_id[i];
			frm_pick_id.push_back( frm_id[id] );
			cout << frm_id[id] << " ";
		}
		cout << endl;

		LcVideoReadVec sel_video( *my_reader);

		sel_video.set( frm_pick_id );

		bagging.setClassifier( my_setting.getClassifier());
		bagging.setFeatureCode( my_setting.feature_code_string.c_str() );
		bagging.setReader( &sel_video );

		bagging.veb = 1;

		{
			FILE * fid = fopen("bagging_config.txt","r");
			int n_classifier; int instance_limit;
			fscanf(fid, "%d%d",&n_classifier, &instance_limit);
			bagging.n_classifier = n_classifier;
			bagging.instance_limit = instance_limit;
			fclose(fid);
		}

		bagging.train( sel_video );

		{
			string saving_name = my_reader->root + "classifier_output/bagging/pick_three_";
			bagging.save(saving_name.c_str());
		}



	}

	if(my_setting.IF_TEST)
	{
	
		//LcBagging bagging;
		
		LcVideoRead * train_reader = my_setting.getTrainVideop();
		LcVideoRead * test_reader = my_setting.getTestVideop();

		vector< float > avg_lbs; avg_lbs.clear();
		avg_lbs.reserve( test_reader->getN() + 10);

		vector< int > frm_id; frm_id.clear();
		frm_id.reserve( test_reader->getN() + 10);

		for(int i = 0; i < 10000; i++)
		{
			Mat frm;

			int statu = test_reader->readNext( frm );

			if(statu) break;

			Mat gt;

			test_reader->getLabel( gt );

			Mat gt_float;

			gt.convertTo( gt_float, 5);

			float _avg_lb = lc::reduceMat( gt_float, CV_REDUCE_AVG);

			avg_lbs.push_back( _avg_lb );	
			frm_id.push_back( test_reader->getf());
		}

		vector< int > sort_id;		

		lc::argsort( avg_lbs, sort_id );

		vector< bool > bo( sort_id.size(), false);

		for(int i = 0 ;i < pick_num ; i++) bo[ sort_id[i] ] = true;

		vector< int > frm_pick_id; frm_pick_id.clear();

		for(int i = 0 ;i < frm_id.size() ; i++)
		{
			if(bo[i]) continue;

			frm_pick_id.push_back( frm_id[i] );			
		}

		LcVideoReadVec sel_video( *test_reader);

		sel_video.set( frm_pick_id );

		

				
		if(!my_setting.IF_TRAIN)
		{
		
			bagging.setClassifier( my_setting.getClassifier());
			bagging.setFeatureCode( my_setting.feature_code_string.c_str() );
			bagging.setReader( &sel_video );

			bagging.veb = 1;
			{
				string saving_name = test_reader->root + "classifier_output/bagging/pick_three_";
				bagging.load(saving_name.c_str());
			}
		}

		vector< LcValidator > validator_array;
		bagging.predict( sel_video, validator_array);

		for(int i = 0 ; i < (int) validator_array.size() ; i++)
		{
			validator_array[i].display();
		}

		{
			string report_name = "./report/bagging_report_" + my_setting.train_video_name + "_on_"
				+ my_setting.test_video_name + "_v_" + my_setting.feature_code_string + ".txt";
			FILE * fout = fopen( report_name.c_str(),"w");
			for(int i = 0 ; i < (int) validator_array.size() ; i++)
			{
				fprintf(fout,"%f\t%f\t%f\t%f\t%f\n", validator_array[i].getF1(),
					validator_array[i].tp,validator_array[i].fp,validator_array[i].fn,validator_array[i].tn);
			}
			fclose(fout);
		}

	}	

	return 0;
}